import os
import time
from string import Template

import cv2 as cv
import numpy as np
import pytesseract
import pymysql


def tap(x, y):
    """
    模拟点击
    :param x:
    :param y:
    :return:
    """
    command_temp = Template("adb shell input tap ${x} ${y}")
    command = command_temp.substitute(x=x, y=y)
    os.system(command)


mysql_connect = pymysql.connect(
    host="localhost",
    user="root",
    passwd="123456",
    db="baidu_idiom",
    charset='utf8',
    cursorclass=pymysql.cursors.DictCursor
)
cursor = mysql_connect.cursor()


def idiom_request(data):
    sql_where = []
    if data[0].find("-") == -1:
        sql_where.append(" q1 = '" + str(data[0]) + "'")
    if data[1].find("-") == -1:
        sql_where.append(" q2 = '" + str(data[1]) + "'")
    if data[2].find("-") == -1:
        sql_where.append(" q3 = '" + str(data[2]) + "'")
    if data[3].find("-") == -1:
        sql_where.append(" q4 = '" + str(data[3]) + "'")
    if len(sql_where) > 1:
        sql_where_str = " and ".join(sql_where)
    elif len(sql_where) == 1:
        sql_where_str = sql_where[0]
    else:
        return []

    sql = "select concat(q1, q2, q3, q4) as res from idiom_with_four_words_back where " + sql_where_str
    # print(sql)
    res = cursor.execute(sql)
    res_data = cursor.fetchmany(res)
    if len(res_data) > 0:
        tmp_data = []
        for d in res_data:
            tmp_data.append(d['res'])
        return tmp_data
    else:
        return []


class NumberOne:

    def __init__(self):
        self.img = cv.imread('demo.jpg')

        # 问题基础配置
        self.question_w_start = 34
        self.question_h_start = 312
        self.question_w_num = 9
        self.question_h_num = 9
        self.question_w = 104
        self.question_space = 9
        self.question_fix = 10
        self.question_r_w = self.question_w - 2 * self.question_fix
        # 答案基础配置
        self.answer_w_start = 33
        self.answer_h_start = 1550
        self.answer_w_num = 8
        self.answer_h_num = 5
        self.answer_w = 120
        self.answer_space = 9
        self.answer_fix = 16
        self.answer_r_w = self.answer_w - 2 * self.answer_fix

        # 图片

        self.question_color_img = np.zeros([self.question_r_w * self.question_h_num,
                                            self.question_r_w * self.question_w_num, 3], np.uint8)

        self.answer_color_img = np.zeros([self.answer_r_w * self.answer_h_num,
                                          self.answer_r_w * self.answer_w_num, 3], np.uint8)

        self.question_str_img = np.zeros([self.question_r_w,
                                          self.question_r_w * self.question_h_num * self.question_w_num, 3], np.uint8)
        self.answer_str_img = np.zeros([self.answer_r_w,
                                        self.answer_r_w * self.answer_h_num * self.answer_w_num, 3], np.uint8)

        # 数据

        self.question_code = np.zeros([self.question_r_w * self.question_h_num,
                                       self.question_r_w * self.question_w_num], np.uint8)
        self.answer_code = np.zeros([self.answer_r_w * self.answer_h_num,
                                     self.answer_r_w * self.answer_w_num], np.uint8)

        self.question_str_num = 0
        self.answer_str_num = 0

        self.question_str_arr = []
        self.answer_str_arr = []

        self.question_str_position = []
        self.answer_str_position = []

        self.get_question_img()
        self.get_answer_img()

        self.idioms = []

        _, self.question_str_binary_img = cv.threshold(self.question_str_img, 200, 255, cv.THRESH_BINARY)
        _, self.answer_str_binary_img = cv.threshold(self.answer_str_img, 200, 255, cv.THRESH_BINARY)

        self.question_str_arr = self.get_img_str(self.question_str_binary_img)
        self.answer_str_arr = self.get_img_str(self.answer_str_binary_img)

        self.question_str_position = self.str_fill(self.question_h_num, self.question_w_num,
                                                   self.question_str_arr, self.question_code)
        self.answer_str_position = self.str_fill(self.answer_h_num, self.answer_w_num,
                                                 self.answer_str_arr.copy(), self.answer_code)

        self.get_idioms()
        self.idiom_search()

    def str_fill(self, h_num, w_num, str_arr, code):
        position = []
        for i in range(0, h_num):
            tmp = []
            for j in range(0, w_num):
                if code[i][j] == 2:
                    tmp.append(str_arr.pop(0))
                elif code[i][j] == 1:
                    tmp.append('?')
                else:
                    tmp.append('')
            position.append(tmp)
        return position

    def get_question_img(self):
        for i in range(0, self.question_h_num):
            y_s = i * (self.question_w - 2 * self.question_fix)
            y_e = (i + 1) * (self.question_w - 2 * self.question_fix)

            for j in range(0, self.question_w_num):
                x_s = j * (self.question_w - 2 * self.question_fix)
                x_e = (j + 1) * (self.question_w - 2 * self.question_fix)

                x1, y1, x2, y2 = self.get_position(self.question_w_start, self.question_h_start, self.question_w,
                                                   self.question_space, self.question_fix, i, j)
                tmp_img = self.clip_img(x1, y1, x2, y2)

                self.question_color_img[y_s:y_e, x_s:x_e] = tmp_img

                gray_img = cv.cvtColor(tmp_img, cv.COLOR_BGR2GRAY)

                tm_mean = np.mean(gray_img)

                # print(i + 1, j + 1, tm_mean)

                # 0/空白; 1/待填充;2/文字
                if tm_mean < 80:
                    self.question_code[i][j] = 1
                    pass
                elif tm_mean < 100:
                    self.question_code[i][j] = 0
                    pass
                else:
                    self.question_code[i][j] = 2

                    tmp_y_s = 0
                    tmp_y_e = self.question_r_w

                    tmp_x_s = self.question_str_num * self.question_r_w
                    tmp_x_e = tmp_x_s + self.question_r_w

                    self.question_str_img[tmp_y_s:tmp_y_e, tmp_x_s:tmp_x_e] = tmp_img

                    self.question_str_num += 1
                    pass
        # 删除空白
        tmp_y_s = 0
        tmp_y_e = self.question_r_w

        tmp_x_e = self.question_str_num * self.question_r_w
        self.question_str_img = self.question_str_img[tmp_y_s:tmp_y_e, 0:tmp_x_e]

    def get_answer_img(self):
        for i in range(0, self.answer_h_num):
            y_s = i * (self.answer_w - 2 * self.answer_fix)
            y_e = (i + 1) * (self.answer_w - 2 * self.answer_fix)

            for j in range(0, self.answer_w_num):
                x_s = j * (self.answer_w - 2 * self.answer_fix)
                x_e = (j + 1) * (self.answer_w - 2 * self.answer_fix)

                x1, y1, x2, y2 = self.get_position(self.answer_w_start, self.answer_h_start, self.answer_w,
                                                   self.answer_space, self.answer_fix, i, j)
                tmp_img = self.clip_img(x1, y1, x2, y2)

                self.answer_color_img[y_s:y_e, x_s:x_e] = tmp_img

                gray_img = cv.cvtColor(tmp_img, cv.COLOR_BGR2GRAY)

                tmp_mean = np.mean(gray_img)

                if tmp_mean < 150:
                    self.answer_code[i][j] = 0
                else:
                    self.answer_code[i][j] = 2

                    tmp_y_s = 0
                    tmp_y_e = self.answer_r_w

                    tmp_x_s = self.answer_str_num * self.answer_r_w
                    tmp_x_e = tmp_x_s + self.answer_r_w

                    self.answer_str_img[tmp_y_s:tmp_y_e, tmp_x_s:tmp_x_e] = tmp_img

                    self.answer_str_num += 1

                # print(i+1, j+1, tmp_mean)

        # 删除空白
        tmp_y_s = 0
        tmp_y_e = self.answer_r_w

        tmp_x_e = self.answer_str_num * self.answer_r_w
        self.answer_str_img = self.answer_str_img[tmp_y_s:tmp_y_e, 0:tmp_x_e]

    def clip_img(self, x1, y1, x2, y2):

        return self.img[y1:y2, x1:x2]

    def get_position(self, w_start, h_start, w, space, fix, i, j):
        x1 = w_start + j * w + j * space + fix
        y1 = h_start + i * w + i * space + fix

        x2 = w_start + (j + 1) * w + j * space - fix
        y2 = h_start + (i + 1) * w + i * space - fix

        return x1, y1, x2, y2

    def get_idioms(self):
        for i in range(0, self.question_h_num):
            for j in range(0, self.question_w_num):
                if j + 3 <= self.question_w_num:
                    res = True
                    tmpL = []
                    for h in range(0, 4):
                        if self.question_code[i][j + h] == 0:
                            res = False
                            break
                        if self.question_code[i][j + h] == 2:
                            # print(i, j+h)
                            tmpL.append(self.question_str_position[i][j + h])
                            # tmpL.append(str(i) + '-' + str(j + h))
                            pass
                        else:
                            tmpL.append(str(i) + '-' + str(j + h))
                            # tmpL.append('?')
                    if res:
                        self.idioms.append(tmpL)

                if i + 3 <= self.question_h_num:
                    res = True
                    tmpL = []
                    for h in range(0, 4):
                        if self.question_code[i + h][j] == 0:
                            res = False
                            break
                        if self.question_code[i + h][j] == 2:
                            tmpL.append(self.question_str_position[i + h][j])
                            pass
                        else:
                            tmpL.append(str(i + h) + '-' + str(j))
                            # tmpL.append('?')
                    if res:
                        self.idioms.append(tmpL)

    def get_img_str(self, img):
        s = pytesseract.image_to_string(img, lang='chi_sim')  # 不加lang参数的话，默认进行英文识别
        return s.split(' ')

    def unknown_str_num(self, idiom):
        j = 0
        for i in idiom:
            if i.find('-') == -1:
                j += 1
        return j

    def idiom_search(self):

        """
        精确查询, 查询顺序： 3 个字符， 2个字符， 1个字符
        """
        has_exact = True
        while has_exact:
            do_one = False

            for i in [3, 2, 1]:
                for idiom in self.idioms:
                    if self.unknown_str_num(idiom) == i:
                        has_exact = self.idiom_exact_search(idiom)

            if do_one is False:
                has_exact = False
        print('exact search finish')
        print(self.idioms)
        print(self.answer_str_arr)

    def idiom_exact_search(self, idioms):
        """
        精确查找: 通过字典进行精确查找
        :return:
        """
        wait_fill_index = []
        wait_fill_position = []

        for i in range(0, len(idioms)):
            if idioms[i].find('-') != -1:
                wait_fill_index.append(i)
                wait_fill_position.append(idioms[i])

        idiom_res = idiom_request(idioms)
        if len(idiom_res) < 0:
            return False

        for res in idiom_res:
            fill_str = []
            for i in wait_fill_index:
                fill_str.append(res[i])
            is_ok = True
            for s in fill_str:
                if s not in self.answer_str_arr:
                    is_ok = False
            if is_ok:
                # 删除答案
                for s in fill_str:
                    self.answer_str_arr.remove(s)
                print(res)
                self.do_it(wait_fill_position, fill_str)
                return True
        return False
        # print(self.answer_str_position)
        # print(self.answer_str_arr)
        # print(wait_fill_index)
        # print(wait_fill_position)
        # exit(1)
        #
        # print(idiom_res)
        return False

    def idiom_random_search(self):
        """
        随机尝试: 由于部分文字识别错误或者成语不存在与数据库, 根据当前的结果进行随机匹配
        :return:
        """

    def do_it(self, position, fill_str):
        """
        先点击问题， 然后点击答案
        校验操作是否正确
            1. 如果不正确，
                点击问题， 回退所有答案
            2. 如果正确
                删除答案字符列表
                清空答案字符串位置的字符
        """
        operate = []

        """
        遍历 position ， 转换问题坐标
        """
        for i in range(0, len(position)):
            tmp_dic = {'question_position_index': self.get_question_position(position[i])[0],
                       'question_position': self.get_question_position(position[i])[1],
                       'answer_position_index': self.get_answer_position(i, fill_str)[0],
                       'answer_position': self.get_answer_position(i, fill_str)[1]}

            operate.append(tmp_dic)
            # 清空已经使用的字符
            self.answer_str_position[tmp_dic['answer_position_index'][0]][tmp_dic['answer_position_index'][1]] = ''
        # for o in operate:
        #     """
        #     点击问题
        #     点击答案
        #     """
        #     tap(o['question_position'][0], o['question_position'][1])
        #     time.sleep(0.3)
        #     tap(o['answer_position'][0], o['answer_position'][1])

        """
        更新成语:
            如果指定位置的字符是正确的, 该字符可能被多个成语使用
        """
        # todo
        # for i in range(0, len(position)):
        #     for j in range(0, len(self.idioms)):
        #         if position[i] in self.idioms[j]:
        #             i_index = self.idioms[j].index(position[i])
        #             self.idioms[j][i_index] = fill_str[i]

    def get_question_position(self, p):
        h, w = p.split('-')
        h = int(h)
        w = int(w)

        x_position = self.question_w_start + w * self.question_space + w * self.question_w + self.question_w / 2
        y_position = self.question_h_start + h * self.question_space + h * self.question_w + self.question_w / 2
        return [[h, w], [x_position, y_position]]

    def get_answer_position(self, i, fill_str):
        for h in range(0, len(self.answer_str_position)):
            for w in range(0, len(self.answer_str_position[h])):
                if fill_str[i] == self.answer_str_position[h][w]:
                    x_position = self.answer_w_start + w * self.answer_space + w * self.answer_w + self.answer_w / 2
                    y_position = self.answer_h_start + h * self.answer_space + h * self.answer_w + self.answer_w / 2

                    return [
                        [h, w],
                        [x_position, y_position]
                    ]


if __name__ == '__main__':
    time1 = time.time()
    number_one = NumberOne()
    time2 = time.time()
    print(format(time2 - time1, '.2f'))
    # number_one.get_question_img()
    # number_one.get_answer_img()

    # cv.imshow('gray1', number_one.question_gray_img)
    # cv.imshow('gray2', number_one.answer_gray_img)

    # cv.imshow('binary_1', number_one.question_color_img)
    # cv.imshow('binary_2', number_one.answer_color_img)
    # cv.namedWindow('binary_1', cv.WINDOW_NORMAL)
    # cv.imshow('binary_1', number_one.question_str_img)
    # cv.imshow('binary_2', number_one.answer_str_img)
    #
    # cv.waitKey(0)
    # cv.destroyAllWindows()
    # print(number_one.question_code)
    # print(number_one.answer_code)
    # print(np.array(number_one.idioms))
    # print(number_one.question_str_arr)
    # print(number_one.answer_str_arr)
    # print(number_one.question_str_position)
    # print(np.array(number_one.question_str_position))
